package com.ionehe.group.common.uaa.ex.application.rest;

import cn.hutool.core.util.StrUtil;
import com.ionehe.group.common.apisecurity.annotation.Decrypt;
import com.ionehe.group.common.apisecurity.annotation.Encrypt;
import com.ionehe.group.common.io.Response;
import com.ionehe.group.common.uaa.ex.application.converter.UserInfoVOConvert;
import com.ionehe.group.common.uaa.ex.application.model.UserChangePasswordVO;
import com.ionehe.group.common.uaa.ex.application.model.UserCheckPasswordVO;
import com.ionehe.group.common.uaa.ex.application.model.UserInfoVO;
import com.ionehe.group.common.uaa.ex.application.model.UserLoginVO;
import com.ionehe.group.common.uaa.ex.domain.service.UaaCommonService;
import com.ionehe.group.common.uaa.ex.domain.service.UserWriteService;
import com.ionehe.group.common.uaa.ex.dto.UserChangePasswordDTO;
import com.ionehe.group.common.uaa.ex.dto.UserDetailDTO;
import com.ionehe.group.common.uaa.ex.dto.UserInfoDTO;
import com.ionehe.group.common.uaa.ex.dto.UserLoginDTO;
import com.ionehe.group.common.uaa.ex.enums.ErrorMessages;
import com.ionehe.group.common.uaa.ex.utils.LoginUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * Copyright (c) 2020 ionehe.com
 * Date: 2020/9/15
 * Time: 下午10:58
 *
 * @author 2020年 <a href="mailto:a@ionehe.com">秀</a>
 *
 * 后台用户管理Controller
 */
@RestController
@Api(value = "uaa-用户登陆相关服务", tags = "uaa-用户登陆相关服务")
@RequestMapping("/api/uaa/user/login")
public class UaaUserLoginController {
    @Autowired
    private UserWriteService userWriteService;
    @Autowired
    private UaaCommonService uaaCommonService;
    @Value("${jwt.tokenHeader:Authorization}")
    private String tokenHeader;
    @Value("${jwt.tokenHead:Bearer }")
    private String tokenHead;
    @Autowired
    private LoginUtils loginUtils;

    @ApiOperation(value = "登录以后返回token")
    @PostMapping
    @Encrypt
    @Decrypt
    public Response<Map<String, String>> login(@Validated @RequestBody UserLoginVO userLoginVO, HttpServletRequest request) {
        userLoginVO.setKey(getRequestIp(request) + ":" + userLoginVO.getKey());
        UserLoginDTO userLoginDTO = UserInfoVOConvert.INSTANCE.vo2dto(userLoginVO);
        userLoginDTO.setIp(getRequestIp(request));
        Response<String> res = userWriteService.login(userLoginDTO);
        if (!res.success() || Objects.isNull(res.getData())) {
            return Response.no(res.getError(), res.getMessage());
        }
        Map<String, String> tokenMap = new HashMap<>();
        tokenMap.put("token", res.getData());
        tokenMap.put("tokenHead", tokenHead);
        return Response.yes(tokenMap);
    }

    @ApiOperation("获取当前登陆用户信息")
    @GetMapping("/getUserByToken")
    @Encrypt
    @Decrypt
    public Response<UserInfoVO> getUserByToken(HttpServletRequest request) {
        String authHeader = request.getHeader(tokenHeader);
        String authToken = authHeader.substring(this.tokenHead.length());
        Response<UserInfoDTO> res = uaaCommonService.getUserByToken(authToken);
        if (!res.success()) {
            return Response.no(res.getMessage());
        }

        return Response.yes(UserInfoVOConvert.INSTANCE.dto2vo(res.getData()));
    }

    @ApiOperation(value = "登出功能")
    @PostMapping(value = "/logout")
    @Encrypt
    @Decrypt
    public Response<Boolean> logout(HttpServletRequest request) {
        String authHeader = request.getHeader(this.tokenHeader);
        if (authHeader == null || !authHeader.startsWith(this.tokenHead)) {
            return Response.no(ErrorMessages.ILLEGAL_OPERATION.toString());
        }
        return userWriteService.logout(authHeader.substring(this.tokenHead.length()), getRequestIp(request));
    }

    @ApiOperation("修改密码")
    @PostMapping("/changePassword")
    public Response<Boolean> changePassword(@RequestBody UserChangePasswordVO userChangePassword, HttpServletRequest request) {
        Response<UserDetailDTO> res = loginUtils.getCurrentUser();
        if (res.success() || res.getData() != null) {
            UserDetailDTO userDetail = res.getData();
            UserInfoDTO user = userDetail.getUserInfoDTO();

            userChangePassword.setTerminal(user.getTerminal());
            userChangePassword.setUsername(user.getPhone());
        }

        Response<Boolean> changeRes = userWriteService.changePassword(UserInfoVOConvert.INSTANCE.vo2dto(userChangePassword));

        if (!changeRes.success()) {
            return changeRes;
        }

        return logout(request);
    }

    @ApiOperation("验证密码是否正确")
    @PostMapping("/checkPassword")
    public Response<Boolean> checkPassword(@RequestBody UserCheckPasswordVO checkPassword) {
        if (StrUtil.isBlank(checkPassword.getPassword())) {
            return Response.no(ErrorMessages.ILLEGAL_PARAMS.toString());
        }
        Response<UserDetailDTO> res = loginUtils.getCurrentUser();
        if (!res.success() || res.getData() == null) {
            return Response.no(ErrorMessages.USER_NOT_LOGIN.toString());
        }

        UserDetailDTO userDetail = res.getData();
        UserInfoDTO user = userDetail.getUserInfoDTO();

        UserChangePasswordDTO password = new UserChangePasswordDTO();

        password.setPassword(checkPassword.getPassword());
        password.setTerminal(user.getTerminal());
        password.setUsername(user.getPhone());
        return userWriteService.checkPassword(password);
    }

    private String getRequestIp(HttpServletRequest request) {
        if (request.getHeader("x-forwarded-for") == null) {
            return request.getRemoteAddr();
        }
        return request.getHeader("x-forwarded-for");
    }
}
